package com.alliky.core.utils

import android.Manifest.permission
import android.annotation.SuppressLint
import android.app.Activity
import android.app.KeyguardManager
import android.content.Context
import android.content.ContextWrapper
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Point
import android.os.Build
import android.provider.Settings
import android.provider.Settings.SettingNotFoundException
import android.util.DisplayMetrics
import android.view.Surface
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import androidx.annotation.RequiresPermission

class ScreenUtils private constructor() {
    companion object {
        fun dp2Px(context: Context?, dp: Float): Float {
            return if (context == null) {
                (-1).toFloat()
            } else dp * density(context)
        }

        @JvmStatic
        fun px2Dp(context: Context?, px: Float): Float {
            return if (context == null) {
                (-1).toFloat()
            } else px / density(context)
        }

        fun density(context: Context): Float {
            return context.resources.displayMetrics.density
        }

        fun dp2PxInt(context: Context?, dp: Float): Int {
            return (dp2Px(context, dp) + 0.5f).toInt()
        }

        fun sp2px(context: Context, spValue: Float): Int {
            val fontScale = context.resources.displayMetrics.scaledDensity
            return (spValue * fontScale + 0.5f).toInt()
        }

        fun px2sp(context: Context, pxValue: Float): Int {
            val fontScale = context.resources.displayMetrics.scaledDensity
            return (pxValue / fontScale + 0.5f).toInt()
        }

        fun getDisplayMetrics(context: Context?): DisplayMetrics {
            var activity: Activity? = null
            activity = if (context !is Activity && context is ContextWrapper) {
                context.baseContext as Activity
            } else {
                context as Activity?
            }
            val metrics = DisplayMetrics()
            activity!!.windowManager.defaultDisplay.getMetrics(metrics)
            return metrics
        }

        /**
         * 获取屏幕大小
         *
         * @param context
         * @return
         */
        fun getScreenPixelSize(context: Context?): IntArray {
            val metrics = getDisplayMetrics(context)
            return intArrayOf(metrics.widthPixels, metrics.heightPixels)
        }

        fun hideSoftInputKeyBoard(context: Context, focusView: View?) {
            if (focusView != null) {
                val binder = focusView.windowToken
                if (binder != null) {
                    val imd =
                        context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                    imd.hideSoftInputFromWindow(binder, InputMethodManager.HIDE_IMPLICIT_ONLY)
                }
            }
        }

        fun showSoftInputKeyBoard(context: Context, focusView: View?) {
            val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
            imm.showSoftInput(focusView, InputMethodManager.SHOW_FORCED)
        }

        fun getScreenWidth(context: Context): Int {
            return context.resources.displayMetrics.widthPixels
        }

        fun getScreenHeight(context: Context): Int {
            return context.resources.displayMetrics.heightPixels
        }

        fun getStatusBarHeight(context: Context): Int {
            var statusBarHeight = 0
            try {
                val c = Class.forName("com.android.internal.R\$dimen")
                val obj = c.newInstance()
                val field = c.getField("status_bar_height")
                val x = field[obj].toString().toInt()
                statusBarHeight = context.resources.getDimensionPixelSize(x)
            } catch (e1: Exception) {
                e1.printStackTrace()
            }
            return statusBarHeight
        }

        fun getAppInScreenheight(context: Context): Int {
            return getScreenHeight(context) - getStatusBarHeight(context)
        }

        /**
         * Return the width of screen, in pixel.
         *
         * @return the width of screen, in pixel
         */
        val screenWidth: Int
            get() {
                val wm = Utils.getApp()
                    .getSystemService(Context.WINDOW_SERVICE) as WindowManager
                    ?: return -1
                val point = Point()
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                    wm.defaultDisplay.getRealSize(point)
                } else {
                    wm.defaultDisplay.getSize(point)
                }
                return point.x
            }

        /**
         * Return the height of screen, in pixel.
         *
         * @return the height of screen, in pixel
         */
        val screenHeight: Int
            get() {
                val wm = Utils.getApp()
                    .getSystemService(Context.WINDOW_SERVICE) as WindowManager
                    ?: return -1
                val point = Point()
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                    wm.defaultDisplay.getRealSize(point)
                } else {
                    wm.defaultDisplay.getSize(point)
                }
                return point.y
            }

        /**
         * Return the application's width of screen, in pixel.
         *
         * @return the application's width of screen, in pixel
         */
        val appScreenWidth: Int
            get() {
                val wm = Utils.getApp()
                    .getSystemService(Context.WINDOW_SERVICE) as WindowManager
                    ?: return -1
                val point = Point()
                wm.defaultDisplay.getSize(point)
                return point.x
            }

        /**
         * Return the application's height of screen, in pixel.
         *
         * @return the application's height of screen, in pixel
         */
        val appScreenHeight: Int
            get() {
                val wm = Utils.getApp()
                    .getSystemService(Context.WINDOW_SERVICE) as WindowManager
                    ?: return -1
                val point = Point()
                wm.defaultDisplay.getSize(point)
                return point.y
            }

        /**
         * Return the density of screen.
         *
         * @return the density of screen
         */
        val screenDensity: Float
            get() = Resources.getSystem().displayMetrics.density

        /**
         * Return the screen density expressed as dots-per-inch.
         *
         * @return the screen density expressed as dots-per-inch
         */
        val screenDensityDpi: Int
            get() = Resources.getSystem().displayMetrics.densityDpi

        /**
         * Set full screen.
         *
         * @param activity The activity.
         */
        fun setFullScreen(activity: Activity) {
            activity.window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
        }

        /**
         * Set non full screen.
         *
         * @param activity The activity.
         */
        fun setNonFullScreen(activity: Activity) {
            activity.window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
        }

        /**
         * Toggle full screen.
         *
         * @param activity The activity.
         */
        fun toggleFullScreen(activity: Activity) {
            val isFullScreen = isFullScreen(activity)
            val window = activity.window
            if (isFullScreen) {
                window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
            } else {
                window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
            }
        }

        /**
         * Return whether screen is full.
         *
         * @param activity The activity.
         * @return `true`: yes<br></br>`false`: no
         */
        fun isFullScreen(activity: Activity): Boolean {
            val fullScreenFlag = WindowManager.LayoutParams.FLAG_FULLSCREEN
            return activity.window.attributes.flags and fullScreenFlag == fullScreenFlag
        }

        /**
         * Set the screen to landscape.
         *
         * @param activity The activity.
         */
        @SuppressLint("SourceLockedOrientationActivity")
        fun setLandscape(activity: Activity) {
            activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
        }

        /**
         * Set the screen to portrait.
         *
         * @param activity The activity.
         */
        @SuppressLint("SourceLockedOrientationActivity")
        fun setPortrait(activity: Activity) {
            activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        }

        /**
         * Return whether screen is landscape.
         *
         * @return `true`: yes<br></br>`false`: no
         */
        val isLandscape: Boolean
            get() = (Utils.getApp().resources.configuration.orientation
                    == Configuration.ORIENTATION_LANDSCAPE)

        /**
         * Return whether screen is portrait.
         *
         * @return `true`: yes<br></br>`false`: no
         */
        val isPortrait: Boolean
            get() = (Utils.getApp().resources.configuration.orientation
                    == Configuration.ORIENTATION_PORTRAIT)

        /**
         * Return the rotation of screen.
         *
         * @param activity The activity.
         * @return the rotation of screen
         */
        fun getScreenRotation(activity: Activity): Int {
            return when (activity.windowManager.defaultDisplay.rotation) {
                Surface.ROTATION_0 -> 0
                Surface.ROTATION_90 -> 90
                Surface.ROTATION_180 -> 180
                Surface.ROTATION_270 -> 270
                else -> 0
            }
        }

        /**
         * Return whether screen is locked.
         *
         * @return `true`: yes<br></br>`false`: no
         */
        val isScreenLock: Boolean
            get() {
                val km = Utils.getApp()
                    .getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
                    ?: return false
                return km.inKeyguardRestrictedInputMode()
            }
        /**
         * Return the duration of sleep.
         *
         * @return the duration of sleep.
         */
        /**
         * Set the duration of sleep.
         *
         * Must hold `<uses-permission android:name="android.permission.WRITE_SETTINGS" />`
         *
         * @param duration The duration.
         */
        @set:RequiresPermission(permission.WRITE_SETTINGS)
        var sleepDuration: Int
            get() = try {
                Settings.System.getInt(
                    Utils.getApp().contentResolver,
                    Settings.System.SCREEN_OFF_TIMEOUT
                )
            } catch (e: SettingNotFoundException) {
                e.printStackTrace()
                -123
            }
            set(duration) {
                Settings.System.putInt(
                    Utils.getApp().contentResolver,
                    Settings.System.SCREEN_OFF_TIMEOUT,
                    duration
                )
            }
    }

    init {
        throw UnsupportedOperationException("u can't instantiate me...")
    }
}